# LuckPay Web Manage System
#
# Copyright (c) 2016 Lucky Byte, Inc.
#
sched   = require 'node-schedule'
pgsql   = require 'pg'
moment  = require 'moment'
uuid    = require 'uuid'

jobs = {}
module.exports = jobs


send_notify = (message, detail, level) ->
    await pgsql.connect settings.pgsql_url, defer err, client, done
    return done(client) and console.log(err) if err

    await client.query "insert into web_notify (
            sender, message, detail, level
        ) values (
            $1, $2, $3, $4
        )", [
        1, message, detail, level
    ], defer err, result
    return done(client) and console.log(err) if err
    done()


# 终端复核后生效
take_term_effect = (term_uuid) ->
    await pgsql.connect settings.pgsql_url, defer err, client, done
    return done(client) and console.log(err) if err

    client.query "begin"
    await client.query \
        "select * from pay_terms_ex where uuid = $1 for update", [
            term_uuid
        ], defer err, result
    return done(client) and console.log(err) if err

    if result.rows.length == 0
        client.query "rollback;"
        return done(client) and console.log(err) if err
        done()
        return console.log '未找到待生效的终端记录'

    record = result.rows[0]

    # 执行这里可能已经离复核有一段时间了，因此需要重新检查记录状态
    if record.rejected
        client.query "rollback"
        done()
        return console.log '终端信息复核时被拒绝，不能生效'
    if not record.checked
        client.query "rollback"
        done()
        return console.log '终端信息尚未复核，不能生效'

    switch record.action
        when 1, 2      # 新增 / 修改终端信息
            await client.query "update pay_terms as t set
                termid = e.termid,           merid = e.merid,
                mapto_term = e.mapto_term,
                tmk = e.tmk,                 macalgo = e.macalgo,
                notes = e.notes,
                inputer = e.inputer,         input_time = e.input_time,
                checker = e.checker,         check_time = e.check_time,
                effect_time = e.effect_time, shaded = false
            from ( select
                termid,         merid,
                mapto_term,
                tmk,            macalgo,
                notes,
                inputer,        input_time,
                checker,        check_time,     effect_time,
                ref_uuid,       uuid
                from pay_terms_ex
            ) as e where t.uuid = e.ref_uuid and e.uuid = $1", [
                record.uuid
            ], defer err, result
            if err
                client.query "rollback"
                done()
                console.log err.message
                console.log err.detail if err.detail
                return sched.scheduleJob moment().add('1', 'm').toDate(), ->
                    take_term_effect term_uuid
            else
                # 同时删除复核表中记录
                await client.query \
                    "delete from pay_terms_ex where uuid = $1", [
                        term_uuid
                    ], defer err, result
                client.query "commit"
                return done()
        when 3      # 删除
            # 删除复核表中记录
            await client.query \
                "delete from pay_terms_ex where uuid = $1", [
                    term_uuid
                ], defer err, result

            await client.query \
                "delete from pay_terms where uuid = $1", [
                    record.ref_uuid
                ], defer err, result
            if err
                client.query "rollback"
                done()
                console.log err.message
                console.log err.detail
                sched.scheduleJob moment().add('1', 'm').toDate(), ->
                    take_term_effect term_uuid
            else
                client.query "commit"
                return done()
        else # action 无效
            send_notify '系统错误', "复核表中 action 无效，UUID = #{term_uuid}", 4


# 增加调度器，让复核后的终端信息生效
jobs.sched_effect = (term_uuid, effect_time) ->
    if typeof effect_time is 'string'
        effect_time = moment(effect_time)

    # 如果时间早于未来的一分钟，则直接生效
    if effect_time.isBefore(moment().add('1', 'm'))
        take_term_effect term_uuid
    else
        sched.scheduleJob effect_time.toDate(), ->
            take_term_effect term_uuid


# 启动时调用此函数注册所有的定时任务
# 注意，如果同时启动多个 NodeJS 服务器，那么每个服务器都注册调度器的话，
# 会浪费资源，同时会有冲突，因此请设置一个主服务器，参考 etc/settings.js
jobs.add_all = ->
    await pgsql.connect settings.pgsql_url, defer err, client, done
    return done(client) and next err if err

    # 复核后待生效终端
    await client.query \
        "select * from pay_terms_ex where checked = true", defer err, result
    return done(client) and next err if err
    done()

    for record in result.rows
        jobs.sched_effect record.uuid, record.effect_time
